//
// Created by ultcrt on 2021/4/27.
//

#include "pwm_driver.h"
#include <unistd.h>
#include <thread>

using namespace GPIO;
using namespace std;

PWMDriver::PWMDriver(int pin, int target_freq, int target_step) {
    keep_running = false;
    pwm_pin = pin;
    freq = target_freq;
    step = target_step;

    setmode(BOARD);
    setup(pwm_pin, OUT, LOW);
    pwm = new PWM(pwm_pin, freq);
}

PWMDriver::~PWMDriver() {
    // Shutdown first to stop PWM signal
    stop();
    cleanup(pwm_pin);
    delete pwm;
}

void PWMDriver::pwm_thread() {
    // Start from duty ratio 0 and decreasing direction (will be revert immediately in loop below)
    double cur_duty_ratio = 0;
    int direction = -step;
    pwm->start(cur_duty_ratio);
    keep_running = true;
    while (keep_running) {
        // Cycling duty ratio btw 0 and 100
        if (cur_duty_ratio >= 100 or cur_duty_ratio <= 0) direction = -direction;
        cur_duty_ratio += direction;
        pwm->ChangeDutyCycle(cur_duty_ratio);
        usleep(10000);
    }

    // Stop emitting PWM signal (controlled by keep_running)
    pwm->stop();
}

void PWMDriver::run() {
    if (!keep_running) {
        thread pwm_t(&PWMDriver::pwm_thread, this);
        pwm_t.detach();
    }
}

void PWMDriver::stop() {
    keep_running = false;
}

void PWMDriver::set_freq(int target_freq) {
    freq = target_freq;
}

void PWMDriver::set_step(int target_step) {
    step = target_step;
}